// 正则表达式有一个匹配原则，贪婪匹配原则，能多就不少
// 如果要打破贪婪模式：(在后面添加一个问号) 非贪婪模式的原则，能少就不多
    var regexp = /a+?/g 
// 正则表达式(regular)
// 转移字符(\)
// 行结束符(\r)(看不出效果)
// 换行(\n)
// 制表符(其实就是tab键)(\t)



// 系统规定字符串不可以多行显示，但是如果要多行的话，可以用转移字符\
document.body.innerHTML = "\
    <div></div>\
    <span></span>";

// RegExp
// 正则表达式的作用：匹配特殊字符或有特殊搭配原则的字符的最佳选择。
// 正则表达式的属性
// i ：忽视大小写
// g ：全局匹配
// m : 执行多次匹配(多行匹配)
// ^ : 以什么开头       // 例如： var regexp = /^a/  匹配以a开头的

// 表达式
// [0-9] : 包含什么字符(0123456789)   [a-z] [A-Z]
// [^a]  : 上尖角号放到表达式里面意思是非  !a除了a以外的
// (red|green|black) : 匹配包含reg或者green或者black的字符; 正则表达式的或是单竖线(|)
// () : 括号里面的叫做表达式


// 元字符
// \w === [0-9A-z_] : \w表示0-9和A-z和一个下划线(_)
// \W === [^\w]   :  正好和\w相反
// \d === [0-9]  : \d表示0到9
// \D === [^0-9] : \D表示除了0到9以外的(非0-9)
// \s === [\t\n\r\v\f ]： 包含制表符 回车符 换行符 垂直换行符 换页符 空格符
// \S === [^s] : \S表示除了非\s以外的东西
// \b === 单词边界 
// \B === 非单词边界
// \n ：查找换行符
// \f : 查找换页符
// \r : 查找回车符
// \t : 查找制表符
// \v : 查找垂直制表符
// . === [^\r\n] ：.等于非的杠r和杠n





// 量词
// n+ : 这个变量可以出现一次到多次
// n* : 这个变量可以出现零次到多次
// n? : 重复零次或一次
// {3, 9} : 匹配多少位可以匹配9位就不5位位
// $ : 以什么结尾



// RegExp对象属性
// regexp.global : 在正则表达式后面有没有写g,有写则返回true 否则返回false
// regexp.ignoreCase : 在正则表达式后面有没有写i,有写则返回true 否则返回false
// regexp.multiline : 在正则表达式后面有没有写m,有写则返回true 否则返回false
// regexp.source : 返回正则表达式的内容
// regexp.test(str) : 判断该字符串是否有我定义的正则表达式的片段
// regexp.lastIndex : 获取和设置下标(和exec配合使用)， regexp.lastIndex = 3;
// regexp.exec(str) : 匹配字符串，第一次匹配第一个，第二次匹配第二个，以此类推，最后到啊null，在调用以此就从0开始



// \1 : 反向引用第一个子表达式里面的内容
// \2 ：反向引用第二个子表达式里面的内容(如果要引用第三个表达式里面的内容就\3)



// 字符串的方法
// str.match(regexp) : 按照正则表达式的规则匹配
// str.search : 返回第一次匹配到的位置(如果匹配不到则返回负一)
// str.split : 字符串拆分
// str.repeat(需要查找的字符, 替换成什么字符) : 替换
// str.toUpperCase() : 把小写字符串变成大写
// str.toLowerCase() : 把大写字符变成小写


var reg = new RegExp();

// 正则表达式的创建方法
// 1.字面量的创建方法
var regexp = /abc/i;  //这个表示正则表达式abc, i是一个属性，表示忽视大小写
var str = 'abcdef';  //创建一个字符串
console.log(regexp.test(str));  //判断str这个字符串有没有regexp规定的片段



// 2.对象的创建方式
var regexp = new RegExp('abc', 'i');  //第一个值写表达式，第二个值写属性
var str = 'fdskfjABClsaj';
console.log(regexp.test(str));  //判断str这个字符串包不包含regexp规定的字符片段



// 字符串里面的一个方法match,按照reg的规则找出来，g就是把reg规则里面的全部都找出来。
var reg = /a/g;
var str = "abcdeaA";
console.log(str.match(reg));




// 例子：我要匹配三个数字相连接的字符串
var str = 'fkdslaruoe43214321i123jfdksafjds234jdfksafjasflds';
var regexp = /[0-9][0-9][0-9]/g;
console.log(str.match(regexp));

// 例子2:: 匹配三个连续的字符包含第一位包含(ab)，第二位包含(cd) 第三位包含(ef);
var regexp = /[ab][cd][ef]/g;
var str = "aceffdasfdsaf";
console.log(str.match(regexp));



// 例子3: 匹配三个连续的字符第一位除了(0-9以外的) 第二位包含(a-z) 第三位包含(a-z)
var regexp = /[^0-9][a-z][a-z]/g;
var str = '0431a43fd143asafdsafsa';
console.log(str.match(regexp));


// 例子4: 匹配包含reg或者green或者black的字符
var regexp = /(reg|green|black)/g;
var string = 'bafjdfjdlsafjblacklsda';
console.log(string.match(regexp));




// 例子5：匹配单词边界abc
var regexp = /\babc/g;
var str = 'abc bcd fdsaf abc';
console.log(str.match(regexp));



// 例子6 : 查找换行符或制表符或回车符
var regexp = /(\n|\t|\r)/g;
var str = 'fd\tsaf\tjd\ns\rkafj\ndsla;fjl;sad';
console.log(str.match(regexp));



// 例子7:使用uncode编码匹配中文(\u4e2d\u56fd是中国的uncode编码)
var regexp = /\u4e2d\u56fd/g;
var string = '前端开发中国开发';
console.log(string.match(regexp));


// 匹配所有字符
var regexp = /[\s\S]/g;
var string = 'fdkasfkjl中国fd13412';
console.log(string.match(regexp));


// 贪婪匹配原则能9个久不5个
var regexp = /\w{5,9}/g;
var str = 'fdsafdjkfjdsl';
console.log(str.match(regexp));



// 使用^开头和$结尾(达到一个限制字符串的作用)
var regexp = /^123$/g;  //字符串必须为 123才能匹配上
var string = '123';
console.log(string.match(regexp));


// 写一个正则表达式，检测首尾是否包含数字。
var regexp = /^\d|\d$/g;
var string = 'fdsafjdsalfjasl5';
console.log(string.match(regexp));


// 写一个正则表达式，检测首尾是否都包含数字。
var regexp = /^\d[\s\S]*\d$/g;
var string = '1fdasjfdfsfj;as1';
console.log(regexp.test(string));




// exec 和 lastIndex使用方法(需要加上g，要不然下标不会动，每次都是从0开始)
var regexp = /ab/g;
var str = 'abababab';
console.log(regexp.lastIndex);
console.log(regexp.exec(str));
console.log(regexp.lastIndex);
console.log(regexp.exec(str));
console.log(regexp.lastIndex);
console.log(regexp.exec(str));
console.log(regexp.lastIndex);
console.log(regexp.exec(str));
console.log(regexp.lastIndex);


// 使用lastIndex更改下标(需要加上g，要不然下标不会动，每次都是从0开始)
var regexp = /ab/g;
var str = 'abababab';
console.log(regexp.exec(str));
regexp.lastIndex = 0;
console.log(regexp.lastIndex);
console.log(regexp.exec(str));




//反向引用第一个子表达式里面的内容
var regexp = /(\a)\1/g;  
var str = "aaaa";
console.log(str.match(regexp));


//三次反向引用第一个表达式里面的内容
var regexp = /(\w)\1\1\1/g;
var str = "aaaafdsafdbbbbfdsaf";
console.log(str.match(regexp));




// 使用反向引用和exec配合使用
var regexp = /(\w)\1(\w)\2/g;
var str = "aabb";
console.log(regexp.exec(str));



// 按照重复的字符拆分字符串
var regexp = /(\w)\1/g;
var string = '4lfjdafirouioqwjflsdaaajffldsajffldsabbjfl;dsaj fdsa';
console.log(string.split(regexp));



// 把字符串里面的a全部替换成-
var str = 'afdsaafdafdsaafadsa';
var regexp = /a/g;
console.log(str.replace(regexp, '-'))
 



// 使用replace把aabb这种类型的字符反过来替换成bbaa这种类型的把后面的放到前面去($1就是引用第一个子表达式, $2就是引用第二个子表达式)  ()括号里面的才叫表达式
var regexp = /(\w)\1(\w)\2/g;
var string = 'fdjsafaabbjfkdsaabbfdsa';
console.log(string.replace(regexp, "$2$2$1$1"));

// 和上面的功能一样但是写法不一样($是引用子表达式的意思)
var regexp = /(\w)\1(\w)\2/g;
var string = 'fdjsafaabbjfkdsaabbfdsa';
console.log(string.replace(regexp, function($, $1, $2) {
    return $2 + $2 + $1 + $1;
}));



// the-first-name 把这种类型的变成theFirstName
// theFirstName
var regexp = /-(\w)/g;
var string = 'the-first-name';
console.log(string.replace(regexp, function($, $1) {
    $1 = $1.toUpperCase();
    return $1;
}))






// 正向预查(或者叫正向断言)
// 需求：我要找一个字符串里面的a，但是这个a后面必须跟着b，b是修饰条件，选择的还是a
var str = 'abaaaaa';
var regexp = /a(?=b)/g;
console.log(str.match(regexp));


// 正向预查(或者叫正向断言)
// 需求：我要找一个字符串里面的a，但是这个a后面不能是b
var str = 'abaaaaa';
var regexp = /a(?!b)/g;
console.log(str.match(regexp));





// 把字符串的每一位拿出来是a的就写入数组中放a，不是的话就用空串表示
var regexp = /a?/g;
var string = 'aabbfdsaaabbaabbfdsaaabb';
console.log(string.match(regexp));




// 字符串去重 
var string = 'aaaaaaabbbbbbbbbbbbbbccccc';
var regexp = /(\w)\1*/g;
console.log(string.replace(regexp, '$1'))





// 给这串数字打点，从后往前查，三位打一次点
var string = '100000000';
var regexp = /(?=(\B)(\d{3})+$)/g;
console.log(string.replace(regexp, "."))


// 检测网址是否合法
var string = prompt("请输入要检测的网址");
function legitimate(string) {
    var regexp = /^(https|http)\:\/\/(www\.)?(\w)+\.(com|cn|net)/gi;
    var panduan = string.match(regexp);
    if(panduan) {
        alert('网址合法');
    }else {
        alert('网址不合法');
    }
}
legitimate(string);







// 匹配一个正常的邮箱：要求正常邮箱,如langli@gmail.com或者是2487016654@qq.com
// var string = 'langli@gmail.com';
var string = '2487016654@qq.com';
var regexp = /\w+\@?\w+\.?(com)$/g;
console.log(string.match(regexp));




// 请对此类电话号码4006-333-186做匹配;
var string = '1106-333-186';
var regexp = /^\d{4}[-]\d{3}[-]\d{3}$/g;
console.log(string.match(regexp));



// 请此类型电话号码(区号3-4位) - 7-8位数做匹配。 0124-15220419
var string = '0114-10220419';
var regexp = /^\d{3,4}-\d{7,8}$/g;
console.log(string.match(regexp));





// 请对手机号码做匹配:限制开头:
// 135、137、138、139、150、151、152、158、159、182、183、187、188、130、131、132、155、185、186 、133 、180 、181 、189
var string = '15220480125';
var regexp = /^(135|137|138|139|150|151|152|158|159|182|183|187|188|130|131|132|155|185|186|133|180|181|189)\d{8}?/g;
console.log(string.match(regexp));



// 请对身份证号码进行匹配:18位数
var identity = '44162220001203601X';
var regexp = /^\d{17}(\d|X)$/gi;
console.log(identity.match(regexp));